我正在努力实现traverse
并sequenceA
独立实施:
这是我traverse'
在以下方面的实施sequenceA
:
traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b) traverse' f x = sequenceA' $ fmap f x
但是,我坚持执行sequenceA
.
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a) sequenceA' x = foldr (\a _ -> fmap helper a) (error "...") x
我使用了一个占位符b
(error "..."
) - 我不知道如何创建b
给定的这些类型.
helper :: (Functor t, Foldable t) => a -> t a helper x = error "TODO"
此外,我使用该helper
函数来获取此代码进行类型检查.但是,再次,这只是一个error
电话.请给我一个如何一般实施的提示sequenceA
.
鉴于:
traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb ta = sequenceA' (fmap a2fb ta)
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = _
洞的理想用途!我们为所有参数命名(不需要进行无点操作,让我们的生活变得非常困难)并在定义应该是一个洞.这会产生:
src/Main.hs:8:14: Found hole ‘_’ with type: f (t a) …
我们现在转向一个返回类似函数的函数f (t a)
.幸运的traverse'
是,现在我们可以改进我们的洞:
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse _ _
src/Main.hs:8:27: Found hole ‘_’ with type: a0 -> f a …
src/Main.hs:8:29: Found hole ‘_’ with type: t a0 …
第一个看起来很乱,但我们知道的东西适合t a0
第二个,这是我们的tfa
.插头和突突:
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse _ tfa
src/Main.hs:8:27: Found hole ‘_’ with type: f a -> f a …
好吧,我们知道具有该签名的功能,那就是id
.所以我们的最终答案是:
traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb ta = sequenceA' (fmap a2fb ta)
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' tfa = traverse id tfa
我们现在可以变得年轻,狂野,无趣(-ish):
traverse' :: (Functor t, Foldable t, Applicative f) => (a -> f b) -> t a -> f (t b)
traverse' a2fb = sequenceA' . fmap a2fb
sequenceA' :: (Functor t, Foldable t, Applicative f) => t (f a) -> f (t a)
sequenceA' = traverse id
这与Prelude中的定义相匹配.〜〜孔